#include "zqm_global.h"
#include "zqm_module.h"
#include "hal_mcu.h"
#include "task_ctrl.h"

// 根据是否节能模式，选择TS参数
short TcGetTS(void)
{
	return (zy_st.ctrl_mode & CTRL_MODE_ECO) ? pm_ctrl.tr : pm_ctrl.ts; // 根据节能模式选择
} 
// 计算开关机点
void TcGetTSK_TSG(short TS, short* TSK, short* TSG)
{
	if(TS == ZY_TEM_AUTO) TS = TcGetTS(); // auto use system temerature parameter
	short c1 = (zy_st.ctrl_mode & CTRL_MODE_HOT) ? -pm_ctrl.c2 : pm_ctrl.c1;	// 制热调整方向相反
	short c2 = (zy_st.ctrl_mode & CTRL_MODE_HOT) ? -pm_ctrl.c1 : pm_ctrl.c2;
	*TSK = TS + c1 + pm_ctrl.c8;		// 有的产品(1001, 1098)这里用C8矫正, 有的产品(966, 976)这里用一个固定值矫正(设置一个假的C8)，兼容统一处理.
	*TSG = TS - c2 + pm_ctrl.c8;
}
// 化霜电磁阀和加热丝的开关
static void TcMeltSwitch(uint8_t on_off)
{
	MeltSwitch(on_off);
}
// 压机运行状态, 压机强制运行(比如化霜预冷) > 压机延时模式(最小停机间隔, 上电延时) > 压机正常开关
// 压机开关: 0: off, 1: on, 2: force on
static void TcCompSwitch(uint8_t on_off)
{
	if (on_off == 1) { 	// 压机真实开机
		// 1. 压机延时模式判断 - 压机延时启动保护/上电延时, 压机实际关机, 这种情况下压机灯闪烁
		if (zy_st.comp_state != COMP_STATE_RUN && zy_st.comp_off_timer < pm_ctrl.c7 * 60) // 最小停机时间保护延时启动
			zy_st.comp_state = COMP_STATE_DELAY;
		else if (zy_st.comp_state != COMP_STATE_RUN && zq_timer_s < (pm_ctrl.cd * 60))  // 上电延时启动
			zy_st.comp_state = COMP_STATE_DELAY;
		else
			zy_st.comp_state = COMP_STATE_RUN;
	}
	else if (on_off == 2)  	// 压机强制开机
		zy_st.comp_state = COMP_STATE_RUN;
	else // 压机关机
		zy_st.comp_state = COMP_STATE_OFF;

	// 开关压机
	if(zy_st.comp_state == COMP_STATE_RUN) {
		zy_st.comp_off_timer = 0;
		MotoSwitch(1);
	}
	else{
		zy_st.comp_on_timer = 0;
		MotoSwitch(0);
	}
}
// 压机自然化霜状态处理 - natural defrost, return: 1-化霜中,接管压机控制, ; 0-化霜结束, 不管压机控制
static int TcNaturalDefrost(uint8_t *on_off, int span_s)
{
	if (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) { // 强制或正常都可以进入状态
		if (zy_st.defrost_timer > (pm_ctrl.d2 * 60 + pm_ctrl.d4 * 60)) { //除霜实际时间大于(除霜控制时间+排水时间), 除霜结束
			zy_st.comp_mode &= (~COMP_MODE_DEFROST_MASK);
			zy_st.defrost_timer = 0;
			zy_st.defrost_lock_timer = pm_ctrl.c6 * 3600; // 启动化霜后锁定显示倒计时
		}
		else {
			zy_st.defrost_timer += span_s;
		}
		*on_off = COMP_STATE_OFF;
		return 1;
	}
	else {
		// Kg modified 20240902 修改，增加d1=0判断为不启动化霜
		// if (zy_st.comp_on_timer_acc > pm_ctrl.d1 * 3600) { // 压机累计运行时间大于 D1 小时以上，强制停机除霜时间 D2分钟；
		if (pm_ctrl.d1 > 0 && (zy_st.comp_on_timer_acc > pm_ctrl.d1 * 3600)) { // 压机累计运行时间大于 D1 小时以上，强制停机除霜时间 D2分钟；
			zy_st.comp_on_timer_acc = zy_st.defrost_timer = zy_st.defrost_drain_timer = 0;
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_AUTO;
		}
		return 0;
	}
}
// 压机电热化霜状态处理 - heating wire defrost, return: 1-化霜中,接管压机控制, ; 0-化霜结束, 不管压机控制
static int TcHeatingDefrost(uint8_t *on_off, int span_s)
{
	zy_st.defrost_timer += span_s;

	switch (zy_st.comp_mode & COMP_MODE_DEFROST_MASK)
	{
	case COMP_MODE_DEFROST_AUTO:
		*on_off = 2; 		// 强制开压机
		TcMeltSwitch(0); 	// 关电磁阀和加热丝
		zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_PRE;
		zy_st.defrost_timer = 0;
		return 1;
	case COMP_MODE_DEFROST_PRE:
		*on_off = 2; // 强制开压机
		TcMeltSwitch(0); 	// 关电磁阀和加热丝
		if (zy_st.defrost_timer > (pm_ctrl.d5 * 60)) {//预冷时间大于d5, 除霜预冷状态结束, 开始正式除霜
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_RUN;
			zy_st.defrost_timer = 0;
		}
		return 1;
	case COMP_MODE_DEFROST_RUN:
		*on_off = 2; 		// 强制开压机
		TcMeltSwitch(1); 	// 开电磁阀和加热丝
		if (zy_st.defrost_m_temp >= pm_ctrl.d6 || zy_st.defrost_timer > (pm_ctrl.d7 * 60)) {//化霜传感器温度达到d6或者除霜实际时间大于d7, 除霜状态结束, 开始正式排水
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_DRAIN;
			*on_off = 0; // 预先设置压机状态为关机, 不然压机还在开机, mode已经切换到排水，风机会启动一瞬间(50ms)
			zy_st.defrost_timer = 0;
		}
		return 1;
	case COMP_MODE_DEFROST_DRAIN:
		*on_off = 0; // 强制关压机
		TcMeltSwitch(1); 	// 关电磁阀和加热丝 - 2024/08/05, 应客户紧急需求，d4时间改为开电磁阀和加热丝
		if (zy_st.defrost_timer > (pm_ctrl.d4 * 60)) {// 排水时间大于d4, 结束除霜
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK);
			zy_st.defrost_timer = 0;
			zy_st.defrost_lock_timer = pm_ctrl.c6 * 3600; // 启动化霜后锁定显示倒计时
		}
		return 1;
	case COMP_MODE_DEFROST_FORCE:
		*on_off = 2; // 强制开机
		TcMeltSwitch(1); 	// 开电磁阀和加热丝
		if (zy_st.defrost_timer > (pm_ctrl.d7 * 60)) {//强制化霜除霜实际时间大于d7, 除霜状态结束, 开始排水
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_DRAIN2;
			*on_off = 0; // 预先设置压机状态为关机, 不然压机还在开机, mode已经切换到排水，风机会启动一瞬间(50ms)
			zy_st.defrost_timer = 0;
		}
		return 1;
	case COMP_MODE_DEFROST_DRAIN2:
		*on_off = 0; // 强制关机
		TcMeltSwitch(1); 	// 关电磁阀和加热丝 - 2024/08/05, 应客户紧急需求，d4时间改为开电磁阀和加热丝
		if (zy_st.defrost_timer > (pm_ctrl.d4 * 60)) {// 排水时间大于d4, 结束除霜
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK);
			zy_st.defrost_timer = 0;
			zy_st.defrost_lock_timer = pm_ctrl.c6 * 3600; // 启动化霜后锁定显示倒计时
		}
		return 1;
	default:
		TcMeltSwitch(0); 	// 关电磁阀和加热丝
		if (pm_ctrl.d3 > 0 && zy_st.defrost_timer > pm_ctrl.d3 * 3600) { // 上电时间大于D3小时以上，开始除霜
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_AUTO;
			zy_st.defrost_timer = 0;
		}
		return 0;
	}
}
// 压机保护处理 - 1-保护中,接管压机控制, ; 0-保护结束, 不管压机控制
static int TcCompProtection(uint8_t* on_off, int span_s)
{
	if (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) { // 强制或正常都可以进入状态
		if (zy_st.defrost_timer > (pm_ctrl.d2 * 60)) { //除霜实际时间大于(除霜控制时间+排水时间), 除霜结束
			zy_st.comp_mode &= (~COMP_MODE_DEFROST_MASK);
			zy_st.defrost_timer = 0;
			zy_st.defrost_lock_timer = 0; // 关闭锁定时间
		}
		else {
			zy_st.defrost_timer += span_s;
		}
		*on_off = COMP_STATE_OFF;
		return 1;
	}
	else {
		if (pm_ctrl.d1 > 0 && zy_st.comp_on_timer > pm_ctrl.d1 * 3600) { // D1参数有效(>0)且压机累计运行时间大于 D1 小时以上，强制停机除霜时间 D2分钟；
			zy_st.defrost_timer = zy_st.defrost_drain_timer = 0;
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_AUTO;;
		}
		return 0;
	}
}
// 压机强制运行处理 - 1-保护中,接管压机控制, ; 0-保护结束, 不管压机控制
static int TcCompForce(uint8_t* on_off, int span_s)
{
	if (zy_st.comp_mode & COMP_MODE_FROCE) {
		if (zy_st.comp_cc > pm_ctrl.cf*3600) { // 强制运行时间到，退出强制制冷
			zy_st.comp_cc = 0;
			zy_st.comp_mode &= ~COMP_MODE_FROCE;
		}
		else if(zy_st.d_temp <= pm_ctrl.al && !(zy_st.alarm & ZQ_ALARM_SENSOR)) { // 显示温度低于低温报警温度， 退出强制制冷
			zy_st.comp_cc = 0;
			zy_st.comp_mode &= ~COMP_MODE_FROCE;
		}
		else{
			if(zy_st.comp_state == COMP_STATE_RUN) zy_st.comp_cc += span_s;  // 压机run的时候才能计时，不然压机延迟启动也会被计入。
			*on_off = 1;
			return 1;
		}
	}
	else
		zy_st.comp_cc = 0;
	return 0;
}
// 压机传感器故障运行模式 - 返回：1-接管压机控制, ; 0-不管压机控制。 运行开C3，关C4，如果C3=0表示该功能不起作用
static int TcCompSensorErr(uint8_t* on_off, int span_s)
{
	if (zy_st.alarm & ZQ_ALARM_SENSOR) {
		if (CFG_DEVICE_TYPE == 961 || CFG_DEVICE_TYPE == 967) { // 冷热型传感器故障要求无强电输出
			*on_off = COMP_STATE_OFF;
		}
		else if (zy_st.sensor_fault_on < (pm_ctrl.c3 * 60)) {
			*on_off = COMP_STATE_RUN;
			if(zy_st.comp_state == COMP_STATE_RUN) // 压机运行时才能计时, 遇到压机延时启动保护，要顺延压机故障启动时间计数
				zy_st.sensor_fault_on += span_s; 
		}
		else if (zy_st.sensor_fault_off < (pm_ctrl.c4 * 60)) {
			zy_st.sensor_fault_on = pms_spec[pm_idx.c3].max * 60; // kg modified 20240423 - 如果C4期间修改C3变大, 会导致上面C3的判断又被触发, 所以加保护C4时候把sensor_fault_on设到最大值
			*on_off = COMP_STATE_OFF;
			zy_st.sensor_fault_off += span_s;
		}
		else{
			*on_off = COMP_STATE_OFF;
			zy_st.sensor_fault_on = zy_st.sensor_fault_off = 0;  // 清除计时, 下一轮故障开关机开始
		}
		zy_st.comp_mode |= COMP_MODE_FAULT;
		return 1;
	}
	else {
		zy_st.sensor_fault_on = zy_st.sensor_fault_off = 0;
		zy_st.comp_mode &= (~COMP_MODE_FAULT);
		return 0;
	}
}
// 压机正常运行处理 - 1-保护中,接管压机控制, ; 0-保护结束, 不管压机控制
static int TcCompNormal(uint8_t* on_off, int span_s)
{
	short TSK, TSG;
	TcGetTSK_TSG(ZY_TEM_AUTO, &TSK, &TSG);
	zy_st.comp_mode |= COMP_MODE_NORMAL;
	if (zq_timer_s == 0 && zy_st.m_temp > TSG) *on_off = 1; // 秒级上电初始化，若箱内温度高于关机点，则开机
	else if (zy_st.m_temp < TSG) {
		if (CFG_DEVICE_TYPE == 915 && (zy_st.ctrl_mode & CTRL_MODE_COOL)){ // 915 特别要求，冷藏模式停机条件：箱内温度低于关机点温度TSG	// 915 特别要求，冷藏模式停机条件：箱内温度低于关机点温度TSG且压缩机运行时间大于3分钟
			if(zy_st.comp_on_timer > 3*60) *on_off = 0;
		}
		else if (CFG_DEVICE_TYPE == 760) { // 760特别要求，上电后首次到达关机点关机时，延时3分钟关机。
			static int comp_first_off_3min = 3 * 60;
			comp_first_off_3min -= (comp_first_off_3min >= 0) ? span_s : 0;
			if (comp_first_off_3min < 0) *on_off = 0;
		}
		else
			*on_off = 0;
	}
	else if (zy_st.m_temp > TSK) *on_off = 1;
	return 0;
}
static void TcCoolCompCtrl(int span_s)
{
	// 压机四种运行模式, 化霜/保护模式 > 强制制冷模式 > 故障制冷模式 > 正常运行模式(含初次上电特例)
	// 高优先级会打断低优先级控制, 但是低优先级的状态会保持，恢复后继续原来的逻辑。

	// 1. 压机延时模式 -- 在TcSwitchCompressor中处理
	// 2. 控制器关机模式 -- 在Task_TempCtrl中处理
	//uint8_t on_off = (zy_st.comp_state == COMP_STATE_RUN || zy_st.comp_state == COMP_STATE_DELAY) ? 1 : 0;
	uint8_t on_off = (zy_st.comp_state == COMP_STATE_RUN) ? 1 : 0; // kaygle modified 20240516 客人认为压机延时不算压机开逻辑, delay期间要按照关机逻辑判断开关机点

	// 4. 化霜模式
	if (CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026) {
		if (TcHeatingDefrost(&on_off, span_s))
			goto TcCoolCompCtrl_1;
	}
	else if (CFG_DEVICE_TYPE == 1625) {
		if (TcCompProtection(&on_off, span_s))
			goto TcCoolCompCtrl_1;
	}
	else {
		if (TcNaturalDefrost(&on_off, span_s))
			goto TcCoolCompCtrl_1;
	}

	// 5. 强制运行模式
	if(TcCompForce(&on_off, span_s))
		goto TcCoolCompCtrl_1;
	
	// 6. 故障运行模式, 5.4  传感器故障状态控制 运行开C3，关C4，如果C3=0表示该功能不起作用
	if(TcCompSensorErr(&on_off, span_s))
		goto TcCoolCompCtrl_1;

	// 7. 正常运行模式(含上电特殊启动判断)
	TcCompNormal(&on_off, span_s);
TcCoolCompCtrl_1:
	TcCompSwitch(on_off);
}
static void TcFreezeCompCtrl(int span_s)
{
	// 压机四种运行模式, 化霜/保护模式 > 强制制冷模式 > 故障制冷模式 > 正常运行模式(含初次上电特例)
	// 高优先级会打断低优先级控制, 但是低优先级的状态会保持，恢复后继续原来的逻辑。

	// 1. 压机延时模式 -- 在TcSwitchCompressor中处理
	// 2. 控制器关机模式 -- 在Task_TempCtrl中处理
	uint8_t on_off = (zy_st.comp_state == COMP_STATE_RUN) ? 1 : 0;

	// 4. 压机保护模式（借用除霜的参数）
	if (CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026) {	// 电热/热气化霜
		if (TcHeatingDefrost(&on_off, span_s))
			goto TcFreezeCompCtrl_1;
	}
	else {
		if (TcCompProtection(&on_off, span_s))
			goto TcFreezeCompCtrl_1;
	}

	// 5. 强制运行模式
	if(TcCompForce(&on_off, span_s))
		goto TcFreezeCompCtrl_1;
	
	// 6. 故障运行模式, 5.4  传感器故障状态控制 运行开C3，关C4，如果C3=0表示该功能不起作用
	if(TcCompSensorErr(&on_off, span_s))
		goto TcFreezeCompCtrl_1;

	// 7. 正常运行模式(含上电特殊启动判断)
	TcCompNormal(&on_off, span_s);
TcFreezeCompCtrl_1:
	TcCompSwitch(on_off);
}
static void TcHeaterSwitch(uint8_t on_off)
{
	HeaterSwitch(on_off);
	zy_st.heater_state = on_off;
}
static void TcHeaterCtrl(int span_s)
{
	uint8_t on_off = 0;
	// 计算开关机点
	short TSK, TSG;
	TcGetTSK_TSG(ZY_TEM_AUTO, &TSK, &TSG);
	zy_st.comp_mode |= COMP_MODE_NORMAL;  // TODO 关闭压机
	TcCompSwitch(0);
	if (zq_timer_rtc_s_pow == 0 && zy_st.m_temp > TSG) on_off = 1; // 秒级上电初始化，若箱内温度高于关机点，则开机, zq_timer_rtc_s_pow == 2扣除自检2s
	else if (zy_st.m_temp < TSK) on_off = 1;
	else if (zy_st.m_temp > TSG) on_off = 0;

	//if (zq_timer_s < 1) zy_st.heater_state = 0; // 上电稳定一下, 第一秒不开制热
	// 6. 故障运行模式, 961 传感器故障要求无强电输出
	if (zy_st.alarm & ZQ_ALARM_SENSOR) on_off = 0;

	TcHeaterSwitch(on_off);
}

// 5.3蒸发/冷凝风机控制：
static void TcFanSwitch(uint8_t on_off)
{
	FanSwitch(on_off);
	zy_st.fan_state = on_off;
}
static void TcCondenserFanSwitch(uint8_t on_off)
{
	CondenserFanSwitch(on_off);
}
static void TcFanCtrl(int span_s)
{
	uint8_t on_off = 0;
	static int delay = 0;
	if (zq_timer_s == 0) delay = 0; // 初始化, Kg Modified 2023/12/27 增加初始化，防止开关控制器导致风机控制异常(由于zy_timer_s < delay导致)

	// 加热化霜冷冻型, 控制冷凝风机, 化霜关风机
	if (CFG_DEVICE_TYPE == 1004 || CFG_DEVICE_TYPE == 1026) {
		if ((zy_st.comp_mode & COMP_MODE_DEFROST_MASK) == COMP_MODE_DEFROST_RUN || (zy_st.comp_mode & COMP_MODE_DEFROST_MASK) == COMP_MODE_DEFROST_FORCE)
			TcCondenserFanSwitch(0);
		else
			TcCondenserFanSwitch(zy_st.comp_state == COMP_STATE_RUN);
		return;
	}
	// 普通冷冻型, 和915机型风机跟随压机动作, 无风机控制动作
	else if ((zy_st.ctrl_mode & CTRL_MODE_FREEZE) || CFG_DEVICE_TYPE == 915)
		return;
	
	// 普通蒸发风机
	if ((ZQ_BOX_MODE & (CTRL_MODE_COOL | CTRL_MODE_HOT)) == (CTRL_MODE_COOL | CTRL_MODE_HOT)) 	// 蒸发风机，a类(冷热型), 跟随压机动作
		 on_off = (zy_st.comp_state == COMP_STATE_OFF); 
	else // 蒸发风机，b类, 常开
		on_off = 1; 

	if (zy_st.door1_timer > 0 && zy_st.door1_timer <= (2*60)) { // 门开两分钟内， 蒸发风机停止
		on_off = 0;
		delay = zq_timer_s + 10;
	}
	else if(zy_st.door1_timer == 0 && zq_timer_s < delay) { // 开门小于两分钟，关门风机延时10s
		on_off = 0;
	}
	else
		delay = 0;

#if (ZQ_BOX_MODE == (CTRL_MODE_COOL | CTRL_MODE_HOT)) 	// 冷热型传感器故障要求无强电输出
	if(zy_st.alarm & ZQ_ALARM_SENSOR) on_off = 0; 
#endif
	TcFanSwitch(on_off);
}
static uint8_t light_soft_switch = 0; 
void TcLightSoftSwitch(void)
{
	// 灯状态取反
#if(ZQ_FUNC_LIGHT == 1)
	light_soft_switch = (zy_st.light_state == 1) ? 0 : 1;
#endif
}
static void TcLightCtrl(int span_s)
{
#if (ZQ_FUNC_LIGHT == 1)
	uint8_t on_off = 0;

	// 灯控逻辑1：上电开灯
	if (zq_timer_s == 0) 
		zy_st.light_state = light_soft_switch = 1; 
	// ECO控逻辑4：进入ECO模式时关灯，退出ECO模式时开灯
	static uint8_t light_ECO = 0;
	if(zy_st.ctrl_mode & CTRL_MODE_ECO) {
		if(light_ECO == 0) 
			zy_st.light_state = light_soft_switch = light_ECO = 1;
	}
	else {
		if(light_ECO == 1) 
			zy_st.light_state = light_soft_switch = light_ECO = 0;
	}
	// 灯控逻辑2：门开时开灯
	static uint8_t door_state = 0;
	if (zy_st.door1_timer > 0) {
		if(door_state == 0)
			zy_st.light_state = light_soft_switch = door_state = 1;
	} 
	else 
		door_state = 0;
	// 灯控逻辑3：依赖软件开关控制
	zy_st.light_state = light_soft_switch;

	LightSwitch(zy_st.light_state);
#endif
}

// will be called every TASK_PERIOD
void Task_TempCtrl(uint32_t span_s)
{
	// if (zq_timer_50ms <= 50) // 延迟50ms启动控制部分，等待各种数据采集到位。比如：防止门开上电第一秒没侦测到门开，风机就动作了。
	// 	return;
	// 计算压机开关机时长，放到任务顶层逻辑中计算是因为：关控制器/切换到制热模式等情况下都要保持计算停机时间以确保压机延迟保护时间
	if(zy_st.comp_state == COMP_STATE_RUN) {
		zy_st.comp_on_timer += span_s;
		zy_st.comp_on_timer_acc += span_s;
	}
	else
		zy_st.comp_off_timer += span_s;
	// 计算化霜锁定时长
	if (zy_st.m_temp <= zy_st.d_temp) zy_st.defrost_lock_timer = 0;// 当实际测量温度小于或等于显示温度, 清除化霜后显示锁定		
	if(zy_st.defrost_lock_timer > 0) zy_st.defrost_lock_timer -= span_s;
	// 处理控制器状态
	if (zy_st.ctrl_state == CTRL_STATE_OFF) { // 当前控制器关机
		if ((zy_st.ctrl_switch & CTRL_ALL_SWITCH) == CTRL_ALL_SWITCH) { // 各种开关要求开机
			zy_st.ctrl_state = CTRL_STATE_RESET_SELF;				// 重启控制器, 不重启cat1
		}
		return;
	}
	else {	// 当前控制器开机, 检测是否各种开关要求关机
		if ((zy_st.ctrl_switch & CTRL_ALL_SWITCH) != CTRL_ALL_SWITCH) {
			TcCompSwitch(0);
			TcFanSwitch(0);
			CondenserFanSwitch(0);
			TcHeaterSwitch(0);
			zy_st.ctrl_state = CTRL_STATE_OFF;		// turn off controller
			return;
		}
	}
	// 判断是否节能模式 CTRL_MODE_ECO -- 在所有设备控制之前，先判断是否节能模式
	if(pm_ctrl.f9 == 1) { // 用户开启节能模式
		uint16_t year, mon, day, hour, min, sec;
		ZqmGetSysTime(&year, &mon, &day, &hour, &min, &sec);
		if(year >= 2024 && mon > 1) { // 判断系统时间大于2024-01, 说明已经矫正过, 可以作为判断依据
			if(pm_ctrl.f8 >= pm_ctrl.f7 && hour >= pm_ctrl.f7 && hour < pm_ctrl.f8) // 在非营业区间内, AKM要求，f7 = f8表示24小时营业
				zy_st.ctrl_mode |= CTRL_MODE_ECO;
			else if(pm_ctrl.f8 < pm_ctrl.f7 && (hour >= pm_ctrl.f7 || hour < pm_ctrl.f8)) // 也在非营业区间内
				zy_st.ctrl_mode |= CTRL_MODE_ECO;
			else 
				zy_st.ctrl_mode &= ~CTRL_MODE_ECO;
		}
	}
	else
		zy_st.ctrl_mode &= ~CTRL_MODE_ECO;

	// 压缩机/制热器控制
	if (zy_st.ctrl_mode & CTRL_MODE_COOL)  // 冷藏
		TcCoolCompCtrl(span_s);
	else if (zy_st.ctrl_mode & CTRL_MODE_FREEZE)  // 冷冻
		TcFreezeCompCtrl(span_s);
	else if (zy_st.ctrl_mode & CTRL_MODE_HOT)  // 制热
		TcHeaterCtrl(span_s);
	// 6.3.8 风机控
	TcFanCtrl(span_s);
    // 灯控
    TcLightCtrl(span_s);
}

// diagnostic mode will be called every TASK_PERIOD
void Task_DiagTempCtrl(uint32_t span_s, bool StartFlag)
{
	static uint8_t diag_state = 0;
	static int diag_timer = 0;
	diag_timer += span_s;

	if (StartFlag) { // 初始化
		extern short last_disp_tem;
		extern short last_disp_defrost_tem;
		zy_st.ctrl_state = CTRL_STATE_DIAG_1004;
		last_disp_tem = last_disp_defrost_tem = ZY_TEM_INVALID;
		diag_state = diag_timer = 0;
		// 预先恢复到缺省值-23℃
		PmSetValue(pm_idx.ts, -230);
		PmSave();
	}

	// if (zq_timer_50ms <= 50) // 延迟50ms启动控制部分，等待各种数据采集到位。比如：防止门开上电第一秒没侦测到门开，风机就动作了。
	// 	return;
	// 计算压机开关机时长，放到任务顶层逻辑中计算是因为：关控制器/切换到制热模式等情况下都要保持计算停机时间以确保压机延迟保护时间
	if(zy_st.comp_state == COMP_STATE_RUN) {
		zy_st.comp_on_timer += span_s;
		zy_st.comp_on_timer_acc += span_s;
	}
	else
		zy_st.comp_off_timer += span_s;
	// 检测是否各种开关要求关机
	if ((zy_st.ctrl_switch & CTRL_ALL_SWITCH) != CTRL_ALL_SWITCH) {
		TcCompSwitch(0);
		TcFanSwitch(0);
		CondenserFanSwitch(0);
		TcHeaterSwitch(0);
		zy_st.ctrl_state = CTRL_STATE_OFF;		// turn off controller
		return;
	}

	switch(diag_state){
		case 0: { // 按照ts = -15℃运行, 超过42分钟或压缩机到温停机
			// 压缩机/制热器控制
			uint8_t on_off = (zy_st.comp_state == COMP_STATE_RUN) ? 1 : 0;
			// 计算开关机点
			short TSK, TSG;
			TcGetTSK_TSG(-150, &TSK, &TSG);
			zy_st.comp_mode = COMP_MODE_NORMAL;
			if (zy_st.alarm & ZQ_ALARM_SENSOR) on_off = 2; // 传感器故障
			else if (zy_st.m_temp < TSG) on_off = 0;
			else if (zy_st.m_temp > TSK) on_off = 2;
			TcCompSwitch(on_off);
			TcCondenserFanSwitch(zy_st.comp_state); // 冷凝风机控制 - 跟随压机
			TcMeltSwitch(0);

			if(on_off == 0 || diag_timer > 42*60) {// 超过42分钟或压缩机到温停机
				diag_state++;
				diag_timer = 0;
			}
			break;
		}
		case 1: // 停机3分钟
			TcCompSwitch(0);			// 压机 - 停机
			TcCondenserFanSwitch(0); 	// 冷凝风机控制 - 跟随压机
			TcMeltSwitch(0);			// 加热丝/电磁阀 - 关
			if(diag_timer > 3*60) {// 超过42分钟或压缩机到温停机
				diag_state++;
				diag_timer = 0;
			}
			break;
		case 2: // 化霜5分钟
			zy_st.comp_mode = (zy_st.comp_mode & ~COMP_MODE_DEFROST_MASK) + COMP_MODE_DEFROST_RUN;
			// 压缩机/制热器控制
			TcCompSwitch(2);			// 压机 - 化霜强制开机
			TcCondenserFanSwitch(0); 	// 冷凝风机控制 - 化霜关机
			TcMeltSwitch(1);			// 加热丝/电磁阀 - 化霜开机
			if(diag_timer > 5*60) {// 超过42分钟或压缩机到温停机
				diag_state++;
				diag_timer = 0;
			}
			break;
		case 3: // 停机2分钟
			zy_st.comp_mode = COMP_MODE_NORMAL;
			TcCompSwitch(0);			// 压机 - 停机
			TcCondenserFanSwitch(0); 	// 冷凝风机控制 - 跟随压机
			TcMeltSwitch(0);			// 加热丝/电磁阀 - 关
			if(diag_timer > 2*60) {// 超过42分钟或压缩机到温停机
				zy_st.defrost_timer = 0; 		// 化霜时间清零
				zy_st.ctrl_state = CTRL_STATE_RESET_SELF;	// diagnostic结束, 重启控制器
			}
			break;
	}
}
